package com.apes.autoparts.parts.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.autoparts.parts.model.*;
import com.apes.autoparts.parts.repository.*;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.generator.service.SequenceService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.NetUtil;
import com.apes.framework.util.statistics.Statistics;
import com.apes.framework.util.statistics.StatisticsRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

@Service("queryVinService")
public class QueryVinService extends DomainService {

    @Autowired
    private ApiAutoParts91Service apiService;
    @Autowired
    private VinModelRepository vinModelRepository;
    @Autowired
    private SequenceService sequenceService;
    @Autowired
    private AutoModelRepository autoModelRepository;
    @Autowired
    private QueryMainGroupService queryMainGroupService;

    @Autowired
    private VinLabelModelRepository vinLabelModelRepository;

    @Autowired
    private AutopartsLogRepository autopartsLogRepository;

    // 校验vin信息
    public JSONObject checkVinData(SimpleRequest request) {
        JSONObject param = request.getJO();

        JSONObject response = apiService.parseVin(param);
        // 增加第三方数据返回没有数据情况fn.api.getCarDetailInfoForNew
        if (response == null || response.size() == 0 ) {
            response = new JSONObject();
            response.put("resCode",3);
        }
//        // 数据来源第三方也没有
//        if (response.getBoolean("isLiyang") != null && response.getBoolean("isLiyang"))
//            response.put("resCode", 3);
        // 第三方数据返回正常数据，没有resCode字段情况
        if (response.getString("resCode") == null )
            response.put("resCode", 0);

        // selectorId没有
        if (response.getString("selectorId") == null)
            response.put("resCode", 3);
        else if (!queryMainGroupService.checkMainGroupData(response))
            response.put("resCode", 3);
        return response;
    }

    // 查询vin 信息
    public JSONObject queryVin(SimpleRequest request) {
        JSONObject param = request.getJO();
        String PZCXID = param.getString("PZCXID");
        String QCCPMC = param.getString("QCCPMC");
        Boolean publicPage = param.get("publicPage") != null ? param.getBoolean("publicPage") : false ;
        if ( !publicPage && SpringManager.getBean(PartDao.class).searchZPTPBFW(param).getJSONArray("data").size() == 0) return new JSONObject();
        // 增加日志
        JSONObject log = new JSONObject();
        Date beginTime =  new Date();
        log.put("beginTime", beginTime);
        log.put("request", param);
        log.put("method", "queryVin");
        log.put("postId", request.getJO().getJSONObject("saleDept") != null ? request.getJO().getJSONObject("saleDept").getString("id") :"");
        log.put("postName", request.getJO().getJSONObject("saleDept") != null ? request.getJO().getJSONObject("saleDept").getString("name") : "");
        param.remove("PZCXID");
        param.remove("QCCPMC");
        param.remove("saleDpet");
        JSONObject response = apiService.parseVin(param);
        Date endTime = new Date();
        log.put("endTime", endTime);
        log.put("time", endTime.getTime() - beginTime.getTime());
        log.put("response",response);
        this.writerLogging(log);


        if (response == null || response.size() == 0)
            return response = new JSONObject();
        List<VinLabelModel> vinLabelModels = vinLabelModelRepository.findAll(JpaDsl.toCriteriaByEq(
                "vin", param.getString("vin")
        ));
        param = request.getJO();
        JSONArray tempArray = SpringManager.getBean(PartDao.class).queryPartEpcVersion(QCCPMC);

        if (vinLabelModels.size() == 0 && response.size()!= 0){
            VinLabelModel vinLabelModel = new VinLabelModel();
            vinLabelModel.setVin(param.getString("vin"));
            vinLabelModel.setPZCXID(PZCXID);
            vinLabelModel.setQCCPMC(param.getString("QCCPMC"));
            vinLabelModel.setParsing(false);
            vinLabelModel.setLastUpdatedStamp(new Date());
            vinLabelModelRepository.saveAndFlush(vinLabelModel);
        }
       if (tempArray.size() != 0)
        response.put("epcVersion", tempArray.getJSONObject(0).getString("EPC_BBMC"));
        log.put("entTime", System.currentTimeMillis());
        return response;
    }


    /***
     * 处理远端解析数据
     */
    private List<VinModel> handleResponse(JSONObject param) {

        List<VinModel> vinModels = new ArrayList<>();

        // 判断是否多选
        if (param.get("multiModel") != null &&
                param.getJSONObject("multiModel").get("content") != null &&
                param.getJSONObject("multiModel").getJSONArray("content").size() != 0) {

            // 重新查询并循环处理
            List<AutoModel> autoModels = handleSpecialResponse(param);
            autoModels.forEach(autoModel -> {
                vinModels.add(saveVinModel(param.getString("vin"), autoModel));
            });
        } else {
            vinModels.add(saveVinModel(param.getString("vin"), handleResponseBase(param)));
        }
        return vinModels;
    }


    /***
     * 处理特殊值：
     * 例如： Honda:LHGCP168288027506
     */
    private List<AutoModel> handleSpecialResponse(JSONObject param) {
        List<AutoModel> autoModels = new ArrayList<>(); // 返回值


        JSONObject multiModel = param.getJSONObject("multiModel");
        JSONArray content = multiModel.getJSONArray("content");

        JSONObject tempJson;
        JSONObject queryJson = new JSONObject();
        queryJson.put("vin", param.getString("vin"));

        for (int i = 0, len = content.size(); i < len; i++) {
            tempJson = content.getJSONObject(i);
            queryJson.put("selectorId", content.getJSONObject(i).getString("selectorId"));

            // 通过传入的 selectorId 循环查询实际的数据
            JSONObject response = apiService.parseVin(queryJson);
            AutoModel autoModel = handleResponseBase(response);

            // 写入部分车型的特征值
            JSONArray header = multiModel.getJSONArray("header");
            for (int j = 0, len1 = header.size(); j < len1; j++ ) {
                JSONObject item = header.getJSONObject(j);
                ModelConfig modelConfig = new ModelConfig();
                modelConfig.setId(sequenceService.getId(ModelConfig.CONST_TABLE_NAME));
                modelConfig.setKey(item.getString("key"));
                modelConfig.setName(item.getString("value"));
                modelConfig.setValue(tempJson.getString(item.getString("key")));
                modelConfig.setSelectorId(autoModel);
                modelConfig.setTimestamp(new Date());
                autoModel.getModelConfigs().add(modelConfig);
            }

            autoModels.add(autoModelRepository.saveAndFlush(autoModel));
        }
        return autoModels;
    }


    /***
     * 处理远端数据
     */
    private AutoModel handleResponseBase(JSONObject param) {
        // 将数据插入数据库
        AutoModel autoModel = new AutoModel();
        autoModel.setId(sequenceService.getId(AutoModel.CONST_TABLE_NAME));
        autoModel.setSelectorId(param.getString("selectorId"));
        autoModel.setBrandCode(param.getString("brandCode"));
        autoModel.setBrandName(param.getString("brandName"));
        autoModel.setCode(param.getString("code"));
        autoModel.setName(param.getString("name"));
        autoModel.setImageUrl(param.getString("imageUrl"));
        autoModel.setTimestamp(new Date());

        // 属性值
        if (param.get("props") != null && param.getJSONArray("props").size() != 0) {

            param.getJSONArray("props").forEach(obj -> {
                JSONObject item = (JSONObject) obj;

                ModelProp modelProp = new ModelProp();
                modelProp.setId(sequenceService.getId(ModelProp.CONST_TABLE_NAME));
                modelProp.setSelectorId(autoModel);
                modelProp.setKey(item.getString("key"));
                modelProp.setValue(item.getString("value"));
                modelProp.setTimestamp(new Date());
                autoModel.getProps().add(modelProp);
            });
        }

        // 特征值
        if (param.get("features") != null && param.getJSONArray("features").size() != 0) {

            param.getJSONArray("features").forEach(obj -> {
                JSONObject item = (JSONObject) obj;

                ModelFeature modelFeature = new ModelFeature();
                modelFeature.setId(sequenceService.getId(ModelFeature.CONST_TABLE_NAME));
                modelFeature.setSelectorId(autoModel);
                modelFeature.setKey(item.getString("key"));
                modelFeature.setValue(item.getString("value"));
                modelFeature.setTimestamp(new Date());
                autoModel.getFeatures().add(modelFeature);
            });
        }
        return autoModelRepository.saveAndFlush(autoModel);
    }


    /***
     * 保存 vin 匹配车型
     */
    private VinModel saveVinModel(String vin, AutoModel autoModel) {

        VinModel vinModel = new VinModel();
        vinModel.setId(sequenceService.getId(VinModel.CONST_TABLE_NAME));
        vinModel.setVin(vin);
        vinModel.setSelectorId(autoModel);
        vinModel.setTimestamp(new Date());
        return vinModelRepository.saveAndFlush(vinModel);
    }


    //        {
    //            "vin":"LHGCP168288027506"
    //        }


    /**
     *     获取vin 全量数据
     */

    public List<VinModel> queryVinModelAll(SimpleRequest request) {
        JSONObject param = request.getJO();

        // 查看当前是否被解析过
        List<VinModel> vinModels = vinModelRepository.findAll(JpaDsl.toCriteriaByEq(
                "vin", param.getString("vin")
        ));
//        if (vinModels.size() != 0) return vinModels;

        // 获取远端解析数据,去除不必要的参数
        if (param.getString("QCCPMC") != null && param.getString("PZCXID") != null) {
            param.remove("QCCPMC");
            param.remove("PZCXID");
        }
        JSONObject response = apiService.parseVin(param);

        // 获取oa的汽车厂牌名称和配置车型编码
        response.put("QCCPMC", request.getJO().getString("QCCPMC"));
        response.put("PZCXID", request.getJO().getString("PZCXID"));

        List<VinModel> vinModelList = handleResponse(response);
        JSONObject jo = request.getJO();
        for (int i = 0; i < vinModelList.size(); i++) {
            jo.put("brandCode", vinModelList.get(i).getSelectorId().getBrandCode());
            jo.put("selectorId", vinModelList.get(i).getSelectorId().getId());
            request.setData(jo);
            queryMainGroupService.queryMainGroupAll(request);
        }
        return vinModelList;
    }
    public List<VinModel> queryVinModels(JSONObject param, VinLabelModel vinLabelModel) {

        JSONObject response = apiService.parseVin(param);

        if (response.getString("selectorId") == null) {
            vinLabelModel.setParsing(true);
            vinLabelModel.setMassger(response.toJSONString());
            vinLabelModelRepository.saveAndFlush(vinLabelModel);
            return null;
        }
        else if (response.getInteger("resCode") != null) {
            if (response.getInteger("resCode") == 1) {

                vinLabelModel.setParsing(true);
                vinLabelModel.setMassger(response.getString("resMessage"));
                vinLabelModelRepository.saveAndFlush(vinLabelModel);
                return null;


            } else if(response.getInteger("resCode") == 2) {
                vinLabelModel.setParsing(true);
                vinLabelModel.setMassger(response.toJSONString());
                vinLabelModelRepository.saveAndFlush(vinLabelModel);
                return null;
            } else {
                vinLabelModel.setParsing(true);
                vinLabelModel.setMassger(response.toJSONString());
                vinLabelModelRepository.saveAndFlush(vinLabelModel);
                return null;
            }

        }


        List<VinModel> vinModels = handleResponse(response);

        return vinModels;
    }

    public void queryVinModelAll2(SimpleRequest request) throws Exception {
        // 查看当前是否被解析过
        List<VinLabelModel> vinLabelModels = vinLabelModelRepository.findAll();

        JSONObject param = request.getJO();
        for (int i = 0; i < vinLabelModels.size(); i++) {
            if ( vinLabelModels.get(i).isParsing() ) {

                continue;
            } else {
                param.put("vin", vinLabelModels.get(0).getVin());

                JSONObject response = apiService.parseVin(param);

                // 获取oa的汽车厂牌名称和配置车型编码
                response.put("QCCPMC", vinLabelModels.get(0).getQCCPMC());
                response.put("PZCXID", vinLabelModels.get(0).getPZCXID());

                List<VinModel> vinModelList = handleResponse(response);
                JSONObject jo = request.getJO();

                System.out.println("获取车架号数据第 " + i + "次");

                for (int j = 0; j < vinModelList.size(); j++) {
                    jo.put("brandCode", vinModelList.get(j).getSelectorId().getBrandCode());
                    jo.put("selectorId", vinModelList.get(j).getSelectorId().getId());
                    request.setData(jo);
                    queryMainGroupService.queryMainGroupAll(request);

                    System.out.println("获取车架号数据第 " + i + "次,获取主组数据:" + j + "次");

                }
                vinLabelModels.get(i).setParsing(true);
            }
        }

        vinLabelModelRepository.save(vinLabelModels);

    }

    //写入日志
    public void writerLogging(JSONObject json) {
        AutopartsLog autopartsLog = new AutopartsLog();
        autopartsLog.setRequest(json.getString("request"));
        autopartsLog.setPostId(json.getString("postId"));
        json.getJSONObject("response").put("saleDept", json.getString("saleDept"));
        autopartsLog.setResponse(json.getJSONObject("response").toString());
        autopartsLog.setPostName(json.getString("postName"));
        autopartsLog.setName(json.getString("method"));
        autopartsLog.setTime(json.getLong("time"));
        autopartsLog.setBeginTime(json.getDate("beginTime"));
        autopartsLog.setEndTime(json.getDate("endTime"));
        autopartsLogRepository.save(autopartsLog);
    }


}
